/*
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License");  you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * http//www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 *
 * The Original Code is ART Ontology API.
 *
 * The Initial Developer of the Original Code is University of Roma Tor Vergata.
 * Portions created by University of Roma Tor Vergata are Copyright (C) 2007.
 * All Rights Reserved.
 *
 * ART Ontology API was developed by the Artificial Intelligence Research Group
 * (art.uniroma2.it) at the University of Roma Tor Vergata
 * Current information about the ART Ontology API can be obtained at 
 * http//art.uniroma2.it/owlart
 *
 */

/*
 * Contributor(s): Armando Stellato stellato@info.uniroma2.it
 */
package it.uniroma2.art.owlart.models;

import it.uniroma2.art.owlart.exceptions.ModelAccessException;
import it.uniroma2.art.owlart.exceptions.ModelUpdateException;
import it.uniroma2.art.owlart.exceptions.UnsupportedRDFFormatException;
import it.uniroma2.art.owlart.io.RDFFormat;
import it.uniroma2.art.owlart.model.ARTNode;
import it.uniroma2.art.owlart.model.ARTNodeFactory;
import it.uniroma2.art.owlart.model.ARTResource;
import it.uniroma2.art.owlart.model.ARTStatement;
import it.uniroma2.art.owlart.model.ARTURIResource;
import it.uniroma2.art.owlart.model.NodeFilters;
import it.uniroma2.art.owlart.navigation.ARTNamespaceIterator;
import it.uniroma2.art.owlart.navigation.ARTNodeIterator;
import it.uniroma2.art.owlart.navigation.ARTResourceIterator;
import it.uniroma2.art.owlart.navigation.ARTStatementIterator;
import it.uniroma2.art.owlart.navigation.ARTURIResourceIterator;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URL;

/**
 * Model containing basic RDF management methods. This is the sole model which does not contain a default
 * implementation in this library, and is thus a container for those methods which
 * <em>must be implemented</em> for any wrapped RDF management technology
 * 
 * This model supports Named Graphs, so wrapper RDF technologies must also support named graphs or be provided
 * with some extension for supporting them.
 * 
 * <h3>
 * SEMANTICS FOR NAMED GRAPHS IN THESE API</h3>
 * 
 * <p>
 * <b>Legenda:</b>
 * <em> (..., G1, G2, GN) written after the name of an operation means: all the standard arguments for that
 * operation, followed by the set of name named graphs G1, G2...GN. So, for example, (...) means no NG is being
 * specified
 * </em>
 * </p>
 * 
 * <ul>
 * <li><b>add(...)</b> adds the statement to the main unnamed graph ({@link NodeFilters#MAINGRAPH})</li>
 * <li><b>add(..., null</b>) throws an {@link IllegalArgumentException}</li>
 * <li><b>add(..., {@link NodeFilters#ANY})</b>) throws an {@link IllegalArgumentException} (ANY valid only
 * for read/delete)</li>
 * <li><b>listStatements(..., null)</b>) throws an {@link IllegalArgumentException}</li>
 * <li><b>listStatements(...)</b>) list all statements from all NGs</li>
 * <li><b>listStatements(..., {@link NodeFilters#ANY})</b>) list all statements from all NGs (as the previous
 * one)</li>
 * <li><b>listStatements(..., ({@link ARTResource})null)</b>) throws an {@link IllegalArgumentException}</li>
 * <li><b>listStatements(..., {@link NodeFilters#MAINGRAPH})</b>) retrieves stats from the UnnamedGraph (
 * {@link NodeFilters#MAINGRAPH})</li>
 * </ul>
 * <p>
 * {@link NodeFilters#ANY} when used as a NG, returns Statements from all NGs (i.e. from the unnamed NG and
 * all other NGs) but if you put both NodeFilters.ANY and another NG, you will get all statements only once
 * per each NG, ignoring all further NG specifications<br/>
 * es: given a graph composed of graphs: MAIN+ngA+ngB<br/>
 * listStatements(..., ngA, NodeFilters.ANY) returns all statements from all NGs (i.e. from the unnamed NG+ngA
 * and ngB), but will not return again stats from ngA even though it has been specified both directly and
 * undirectly through use of ANY
 * </p>
 * 
 * @author Armando Stellato
 * 
 */
public interface BaseRDFTripleModel extends PrefixMapping, TripleQueryModel, ARTNodeFactory {

	/**
	 * adds the specified triple to graphs <code>graphs</code>
	 * 
	 * @param subject
	 * @param predicate
	 * @param object
	 * @param graphs
	 * @throws ModelUpdateException
	 */
	public void addTriple(ARTResource subject, ARTURIResource predicate, ARTNode object,
			ARTResource... graphs) throws ModelUpdateException;

	/**
	 * add statement <code>stat</code> to graphs <code>graphs</code>
	 * 
	 * @param stat
	 * @param graphs
	 * @throws ModelUpdateException
	 */
	public void addStatement(ARTStatement stat, ARTResource... graphs) throws ModelUpdateException;

	/**
	 * sets the default namespace for the ontology managed by this model
	 * 
	 * @param namespace
	 * @throws ModelUpdateException
	 */
	public void setDefaultNamespace(String namespace) throws ModelUpdateException;

	/**
	 * sets the baseuri for the ontology managed by this model
	 * 
	 * @param uri
	 * @throws ModelUpdateException
	 */
	public void setBaseURI(String uri) throws ModelUpdateException;;

	/**
	 * returns the default namespace of the ontology managed by this model
	 * 
	 * @return
	 */
	public String getDefaultNamespace();

	/**
	 * returns the baseuri of the ontology managed by this model
	 * 
	 * @return
	 */
	public String getBaseURI();

	/**
	 * checks that the triple identified by &lt;<code>subj</code>, <code>pred</code>, <code>obj</code>&gt; is
	 * present in this model, inside one of the graphs specified in <code>graphs</code>
	 * 
	 * @param subj
	 *            the subject of the triple
	 * @param pred
	 *            the predicate of the triple
	 * @param obj
	 *            the object of the triple
	 * @param inferred
	 *            tells if the inference engine of the model is to be used for this retrieval operation
	 * @param graphs
	 *            the graphs where to look for the specified triple
	 * @return true or false according to the presence of the triple in the model
	 * @throws ModelAccessException
	 */
	public abstract boolean hasTriple(ARTResource subj, ARTURIResource pred, ARTNode obj, boolean inferred,
			ARTResource... graphs) throws ModelAccessException;

	/**
	 * checks that the specified statement is present in this model, inside one of the graphs specified in
	 * <code>graphs</code>
	 * 
	 * @param stat
	 *            the statement which is checked inside the model
	 * @param inferred
	 *            tells if the inference engine of the model is to be used for this retrieval operation
	 * @param graphs
	 *            the graphs where to look for the specified statement
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract boolean hasStatement(ARTStatement stat, boolean inferred, ARTResource... graphs)
			throws ModelAccessException;

	/**
	 * returns statements which unify with triples containing <code>subj</code>, <code>pred</code> and
	 * <code>obj</code> in their respective positions. A {@link NodeFilters#ANY} value in one of these
	 * positions is equivalent to putting a wildcard in that position.
	 * 
	 * @param subj
	 *            the subject of the triple
	 * @param pred
	 *            the predicate of the triple
	 * @param obj
	 *            the object of the triple
	 * @return an STStatementIterator over statements in the loaded set of ontologies
	 * @throws ModelAccessException
	 */
	public abstract ARTStatementIterator listStatements(ARTResource subj, ARTURIResource pred, ARTNode obj,
			boolean inferred, ARTResource... graphs) throws ModelAccessException;

	/**
	 * deletes the triple identified by &lt;<code>subject</code>, <code>property</code>, <code>object</code>
	 * &gt; from the specified <code>graphs</code>
	 * 
	 *@param subject
	 *@param property
	 *@param object
	 *@param graphs
	 */
	public abstract void deleteTriple(ARTResource subject, ARTURIResource property, ARTNode object,
			ARTResource... graphs) throws ModelUpdateException;

	/**
	 * deletes the specified statement from graphs <code>graphs</code>
	 * 
	 * 
	 * @param statement
	 * @param graphs
	 * @throws ModelUpdateException
	 */
	public abstract void deleteStatement(ARTStatement statement, ARTResource... graphs)
			throws ModelUpdateException;

	/**
	 * completely clears any RDF statement from the specified graphs
	 * 
	 * @throws ModelUpdateException
	 */
	public abstract void clearRDF(ARTResource... graphs) throws ModelUpdateException;

	/**
	 * list all namespaces used in this model
	 * 
	 * @return
	 * @throws ModelAccessException
	 */
	public ARTNamespaceIterator listNamespaces() throws ModelAccessException;

	/**
	 * adds RDF data to graphs <code>graphs</code> by loading it from inputfile <code>inputFile</code>. Data
	 * in the file must be formatted according to the specified <code>rdfFormat</code>. The specified
	 * <code>baseURI</code> is used for those formats where relative resource names are present and the
	 * baseuri is not present in the file.
	 * 
	 * @param inputFile
	 * @param baseURI
	 * @param rdfFormat
	 * @param graphs
	 * @throws FileNotFoundException
	 * @throws IOException
	 * @throws ModelAccessException
	 * @throws ModelUpdateException
	 * @throws UnsupportedRDFFormatException
	 */
	public void addRDF(File inputFile, String baseURI, RDFFormat rdfFormat, ARTResource... graphs)
			throws FileNotFoundException, IOException, ModelAccessException, ModelUpdateException,
			UnsupportedRDFFormatException;

	/**
	 * adds RDF data to graphs <code>graphs</code> by loading it from url <code>url</code>. Data in the file
	 * must be formatted according to the specified <code>rdfFormat</code>. The specified <code>baseURI</code>
	 * is used for those formats where relative resource names are present and the baseuri is not present in
	 * the file.<br/>
	 * Implementation of this method are expected to use content negotiation to negotiate RDF data with the
	 * server, asking MIME type for the appropriate rdf serialization format (MIME type can be obtained
	 * through {@link RDFFormat#getMIMEType()} method.
	 * 
	 * @param url
	 * @param baseURI
	 * @param rdfFormat
	 * @param graphs
	 * @throws FileNotFoundException
	 * @throws IOException
	 * @throws ModelAccessException
	 * @throws ModelUpdateException
	 * @throws UnsupportedRDFFormatException
	 */
	public void addRDF(URL url, String baseURI, RDFFormat rdfFormat, ARTResource... graphs)
			throws FileNotFoundException, IOException, ModelAccessException, ModelUpdateException,
			UnsupportedRDFFormatException;

	/**
	 * writes RDF data from graphs <code>graphs</code> into file <code>outputFile</code>. Data in the file
	 * will be formatted according to the specified <code>rdfFormat</code>.
	 * 
	 * @param outputFile
	 * @param rdfFormat
	 * @param graphs
	 * @throws IOException
	 * @throws ModelAccessException
	 * @throws UnsupportedRDFFormatException
	 */
	public abstract void writeRDF(File outputFile, RDFFormat rdfFormat, ARTResource... graphs)
			throws IOException, ModelAccessException, UnsupportedRDFFormatException;

	/**
	 * writes RDF data from graphs <code>graphs</code> to output stream <code>os</code>. Data in the file will
	 * be formatted according to the specified <code>rdfFormat</code>.
	 * 
	 * @param os
	 * @param rdfFormat
	 * @param graphs
	 * @throws IOException
	 * @throws ModelAccessException
	 * @throws UnsupportedRDFFormatException
	 */
	public abstract void writeRDF(OutputStream os, RDFFormat rdfFormat, ARTResource... graphs)
			throws IOException, ModelAccessException, UnsupportedRDFFormatException;


	/**
	 * closes the current model, releasing its resources
	 * 
	 * @throws ModelUpdateException
	 */
	public abstract void close() throws ModelUpdateException;

	/**
	 * returns an {@link ARTResourceIterator} over the namedgraphs declared in the global RDF graph
	 * 
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract ARTResourceIterator listNamedGraphs() throws ModelAccessException;

	
	/**
	 * list all resources which appear as subjects of statements having given <code>predicate</code> and
	 * <code>object</code>
	 * 
	 * @param predicate
	 * @param object
	 * @param inferred
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract ARTResourceIterator listSubjectsOfPredObjPair(ARTURIResource predicate, ARTNode object,
			boolean inferred, ARTResource... graphs) throws ModelAccessException;

	/**
	 * list all nodes which appear as objects of statements having given <code>subject</code> and
	 * <code>predicate</code>
	 * 
	 * @param subject
	 * @param predicate
	 * @param inferred
	 * @param contexts
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract ARTNodeIterator listValuesOfSubjPredPair(ARTResource subject, ARTURIResource predicate,
			boolean inferred, ARTResource... graphs) throws ModelAccessException;

	/**
	 * list all uri resources which appear as predicates of statements having given <code>subject</code> and
	 * <code>object</code>
	 * 
	 * @param subject
	 * @param object
	 * @param inferred
	 * @param contexts
	 * @return
	 * @throws ModelAccessException
	 */
	public abstract ARTURIResourceIterator listPredicatesOfSubjObjPair(ARTResource subject, ARTNode object,
			boolean inferred, ARTResource... graphs) throws ModelAccessException;

}